import hashlib
import json
import logging

import aiohttp

logger = logging.getLogger(__name__)


class PaymentAPIImpl:
    def __init__(self, api_token: str, shop_id: str, base_url=None):
        self.api_token = api_token
        self.base_url = base_url
        self.session = aiohttp.ClientSession()
        self.shop_id = shop_id
        self.session.headers.update(
            {
                "Content-Type": "application/json;charset=utf-8",
            }
        )

    def generate_signature(self, data: dict):
        """
        Create signature https://portal.fondy.eu/en/info/api/v1.0/3/#chapter-5
        Takes dict like below and adds "signature" into the "request":

        {
          "request":{
            "order_id":"test123456",
            "order_desc":"test order",
            "currency":"USD",
            "amount":"125",
            "signature":"f0ee6288b9295d3b808bcd8d720211c7201245e1", <-- that
            "merchant_id":"1396424"
          }
        }
        """
        assert "request" in data.keys()
        keys = sorted(data["request"].keys())
        values = [self.api_token]
        values += [data["request"][key] for key in keys]
        values = [v for v in values if v]
        try:
            raw = "|".join(values)
        except Exception as e:
            raise Exception(e, values)

        raw_data = raw.encode("utf-8")
        data["request"]["signature"] = hashlib.sha1(raw_data).hexdigest()

        return json.dumps(data)

    async def send_signed_request(
        self, http_method: str, url_path: str, payload=None
    ) -> bool | str | dict:
        if payload is None:
            payload = {}
        url = self.base_url + url_path
        payload = self.generate_signature(payload)
        params = {"url": url, "data": payload}
        logger.debug(f"Payload: {payload}")

        response = await self._dispatch_request(http_method)(**params)

        try:
            data = await response.json()
        except ValueError:
            data = await response.text()

        if (
            response.status != 200
            or not data["response"]["response_status"] == "success"
        ):
            logger.exception(data)
            logger.exception(json.dumps(payload))
            logger.exception(response.url)
            return False

        return data

    def _dispatch_request(self, http_method: str):
        return {
            "GET": self.session.get,
            "DELETE": self.session.delete,
            "PUT": self.session.put,
            "POST": self.session.post,
        }.get(http_method, "GET")
